#include <stdexcept>
#include <iostream>
#include "../common/PrintUtil.h"
#include "../common/Vertex.h"

using namespace std;

/* 基于邻接表实现的无向图类 */
class GraphAdjList {
public:
    // 邻接表，key: 顶点，value：该顶点的所有邻接顶点
    unordered_map<Vertex*, vector<Vertex*>> adjList;

    /* 在 vector 中删除指定节点 */
    void remove(vector<Vertex*> &vec, Vertex *vet) {
        for (int i = 0; i < vec.size(); i++) {
            if (vec[i] == vet) {
                vec.erase(vec.begin() + i);
                break;
            }
        }
    }

    /* 构造方法 */
    GraphAdjList(const vector<vector<Vertex*>>& edges) {
        for (const vector<Vertex*>& edge : edges) {
            addVertex(edge[0]);
            addVertex(edge[1]);
            addEdge(edge[0], edge[1]);
        }
    }

    /* 获取顶点数量 */
    int size() { return adjList.size(); }

    /* 添加边 */
    void addEdge(Vertex* vet1, Vertex* vet2) {
        if (!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2)
            throw invalid_argument("不存在顶点");
        adjList[vet1].push_back(vet2);
        adjList[vet2].push_back(vet1);
    }

    /* 删除边 */
    void removeEdge(Vertex* vet1, Vertex* vet2) {
        if (!adjList.count(vet1) || !adjList.count(vet2) || vet1 == vet2)
            throw invalid_argument("不存在顶点");
        remove(adjList[vet1], vet2);
        remove(adjList[vet2], vet1);
    }

    /* 添加顶点 */
    void addVertex(Vertex* vet) {
        if (adjList.count(vet)) return;
        adjList[vet] = vector<Vertex*>();
    }

    /* 删除顶点 */
    void removeVertex(Vertex* vet) {
        if (!adjList.count(vet))
            throw invalid_argument("不存在顶点");
        adjList.erase(vet);
        for (auto& [key, vec] : adjList) {
            remove(vec, vet);
        }
    }

    /* 打印邻接表 */
    void print() {
        cout << "邻接表 =" << endl;
        for (auto& adj  : adjList) {
            const auto& key= adj.first;
            const auto& vec = adj.second;
            cout << key->val << ": ";
            PrintUtil::printVector(vetsToVals(vec));
        }
    }
};
